#include "statsxx/machine_learning/Ensemble.hpp"


// jScience
#include "jScience/linalg.hpp" // Matrix<>
#include "jutility.hpp"        // rand_num_uniform_Mersenne_twister()


//
// DESC: Train learners by bootstrapping data.
//
// NOTE: Bootstrap training is used in the following algorithms:
//
//     bagging
//     training + BMA/BMC
//
template<typename T>
inline void Ensemble<T>::train_bootstrap(
                                         const Matrix<double> &X_in,
                                         const Matrix<double> &X_out
                                         )
{
    for( auto i = 0; i < this->learners.size(); ++i )
    {
        // BOOTSTRAP DATA
        Matrix<double> X_in_i(X_in.size(0),X_in.size(1));
        Matrix<double> X_out_i(X_out.size(0),X_out.size(1));

        for( auto j = 0; j < X_in.size(0); ++j )
        {
            int r = rand_num_uniform_Mersenne_twister(0, (X_in.size(0)-1));

            for( auto k = 0; k < X_in.size(1); ++k )
            {
                X_in_i(j,k) = X_in(r,k);
            }

            for( auto k = 0; k < X_out.size(1); ++k )
            {
                X_out_i(j,k) = X_out(r,k);
            }
        }

        // TRAIN
        this->learners[i].f_train(
                                  X_in_i,
                                  X_out_i
                                  );
    }
}
